import type { PropType, VNode } from 'vue'
import { computed, createVNode, defineComponent, ref } from 'vue'
import { offset, useFloating } from "@floating-ui/vue";
import type { Placement } from '@floating-ui/vue'
import { filterEmpty, isBaseType } from '@v-c/utils'
import { useClassnames } from '../../utils/gen-class/index'
import './style/index.less'


export default defineComponent({
  name: "TTooltip",
  props: {
    placement: {
      type: String as PropType<Placement>,
      default: 'bottom-center',
    },
    content: {
      type: String as PropType<string>,
    },
    trigger: {
      type: String as PropType<'hover' | 'click'>,
      default: 'hover',
    },
  },
  setup(props, { slots }) {
    const reference = ref(null);
    const floating = ref(null);

    // 因为props.placement不是响应式的，所以用computed转一下变成响应式
    const placement = computed(() => props.placement)

    const { floatingStyles } = useFloating(reference, floating, {
      placement,
      middleware: [offset(4)],  // 偏移
    });


    const { c } = useClassnames('tooltip')


    const show = ref(false)
    let timer: ReturnType<typeof setTimeout> | undefined
    // 鼠标移入
    const hanelMouseEnter = () => {
      if (props.trigger !== 'hover')
        return

      show.value = true
    }
    // 鼠标移出
    const hanelMouseLeave = () => {
      timer = setTimeout(() => {
        show.value = false
      }, 150)
    }
    // 鼠标点击
    const handleClick = () => {
      if (props.trigger !== 'click')
        return

      show.value = true
    }







    return () => {


      // 写在return函数内默认为响应式，所以不需要用cx函数来实现响应式
      const cls = {
        [c()]: true,
      }


      const renderTooltip = () => {

        if (!reference.value)
          return null  // 如果default（也是reference）节点不存在，直接返回，不需要渲染


        if (!show.value) // 如果show不为true,不需要渲染
          return null
        // 实现鼠标移如提示而提示不消失
        const events = {
          onMouseenter: () => {
            if (timer)
              clearTimeout(timer)
            timer = undefined
          },
          onMouseleave: () => {
            show.value = false
          },
        }


        return (
          <div {...events} class={cls} ref={floating} style={floatingStyles.value}>
            {slots.content ? slots.content?.() : props.content}
          </div>
        )
      }


      // 过滤掉<!-- 这是一个button --> 这个注释节点，不存在slots所获取到的节点中       
      // <t-tooltip > 
      //    <!-- 这是一个button -->
      //     <t-button>111</t-button> 
      // </t-tooltip>
      // filterEmpty可以过滤掉注释节点
      const children = filterEmpty(slots.default?.())
      if (children && children.length < 1)
        return null



      // 错误
      // <t-tooltip > 
      //     <t-button>111</t-button> 
      //     <t-button>222</t-button> 
      // </t-tooltip>
      if (children.length > 1) {
        console.warn('只能存在一个根节点')
        return children
      }




      // 正确
      // <t-tooltip > 
      //     <t-button>111</t-button> 
      // </t-tooltip>
      // 错误
      // <t-tooltip > 
      //     111
      // </t-tooltip>
      // isBaseType(node) 判断是否是简单类型，如果是，返回true
      const node = children[0]
      if (isBaseType(node)) {
        console.warn('TTooltip组件必须存在一个根节点元素')
        return node
      }



      const events = {
        onMouseenter: hanelMouseEnter,
        onMouseleave: hanelMouseLeave,
        onClick: handleClick,
      }
      // 用default插槽获取的元素创建元素，并加上ref=reference
      const tipNode = createVNode(node as VNode, {
        ref: reference,
        ...events,
      })



      return (
        <>
          {tipNode}
          {renderTooltip()}
        </>
      );
    };
  },
});
